package com.testing.DriverSelf;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.testing.common.AutoTools;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.*;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

/**
 * @Classname HttpDriver
 * @Description 类型说明
 * @Date 2022/11/2 21:45
 * @Created by 特斯汀Roy
 */
public class HttpDriver {

    private CloseableHttpClient client;

    private BasicCookieStore cookieStore;

    //默认使用cookie
    private boolean isUseCookie = true;

    //默认使用头域
    private boolean isUseheader=true;

    private Map<String,String> headerMap;

    public HttpDriver() {
        //cookieStore初始化放在构造方法里面。
        cookieStore=new BasicCookieStore();
        headerMap=new HashMap<>();
    }

    public void createClient() {
        if (isUseCookie) {
            client = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
        } else {
            client = HttpClients.custom().build();
        }
    }

    //开关方法，决定接下来是否使用cookie。
    public void useCookie(){
        isUseCookie=true;
    }

    public void notUseCookie(){
        isUseCookie=false;
    }

    public void clearCookie(){
        cookieStore=new BasicCookieStore();
    }

    public void useHeader(){
        isUseheader=true;
    }

    public void notUseHeader(){
        isUseheader=false;
    }

    /**
     * 添加头的时候，用json格式  {“键”:"值"，“键”:"值"}
     * @param headerJson
     */
    public void addHeader(String headerJson){
        //遍历json的每个字段存到map里面。
        JSONObject jsonObject = JSONObject.parseObject(headerJson);
        for (String key : jsonObject.keySet()) {
            headerMap.put(key,jsonObject.getString(key));
        }
        useHeader();
    }

    public void clearHeader(){
        headerMap=new HashMap<>();
        notUseHeader();
    }

    /***
     * get方法封装，异常信息作为失败时候的返回结果。
     * @param url
     * @return
     * @throws IOException
     */
    public String doGet(String url) {
        try {
            createClient();
            HttpGet visit = new HttpGet(url);
            if(isUseheader){
                //遍历添加map中所有头
                for (String headerKey : headerMap.keySet()) {
                    visit.setHeader(headerKey,headerMap.get(headerKey));
                }
            }
            //发送请求并且获取返回结果
            CloseableHttpResponse visitResp = client.execute(visit);
            //从返回结果中获取返回体
            HttpEntity entity = visitResp.getEntity();
            //将返回体解析为字符串。
            String visitResult = EntityUtils.toString(entity, "UTF-8");
            return AutoTools.unicodeDecode(visitResult);
        } catch (Exception e) {
            AutoTools.log.error("get请求" + url + "失败", e.fillInStackTrace());
            return e.fillInStackTrace().toString();
        }
    }


    /**
     * post请求汇总，支持 urlencoded /json/文件上传
     *
     * @param url
     * @param param
     * @param type
     * @return
     */
    public String doPost(String url, String param, String type) {
        try {
            createClient();
            //url和方法
            HttpPost post = new HttpPost(url);
            //根据不同情况拼接请求体和请求头
            switch (type) {
                case "file":
                    //请求体，请求头
                    //创建multipart实体的构造器
                    //RFC6532模式用于处理请求中的中文内容
                    MultipartEntityBuilder meb = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);

                    JSONObject allParams = JSON.parseObject(param);

                    JSONObject fileParams = allParams.getJSONObject("file");
                    for (String key : fileParams.keySet()) {
                        meb.addBinaryBody(key, new File(fileParams.getString(key)));
                    }

                    JSONObject textParams = allParams.getJSONObject("text");
                    //将其中的每个键值对都添加为textbody
                    for (String key : textParams.keySet()) {
                        //Content-type指定请求的charset处理中文。
                        meb.addTextBody(key, textParams.getString(key), ContentType.create("text/plain", Charset.forName("UTF-8")));
                    }
                    HttpEntity entity = meb.build();
                    post.setEntity(entity);
                    break;
                case "url":
                    StringEntity urlParam = new StringEntity(param, "utf-8");
                    urlParam.setContentType("application/x-www-form-urlencoded;charset=utf-8");
                    urlParam.setContentEncoding("utf-8");
                    post.setEntity(urlParam);
                    break;
                case "json":
                    StringEntity jsonParam = new StringEntity(param, "utf-8");
                    jsonParam.setContentType("application/json;charset=utf-8");
                    jsonParam.setContentEncoding("utf-8");
                    post.setEntity(jsonParam);
                    break;
                case "xml":
                    StringEntity xmlParam = new StringEntity(param, "utf-8");
                    xmlParam.setContentType("text/xml;charset=utf-8");
                    xmlParam.setContentEncoding("utf-8");
                    post.setEntity(xmlParam);
                    break;
            }
            if(isUseheader){
                //遍历添加map中所有头
                for (String headerKey : headerMap.keySet()) {
                    post.setHeader(headerKey,headerMap.get(headerKey));
                }
            }

            //发包获取返回结果，并且进行unicode解码。
            String result = EntityUtils.toString(client.execute(post).getEntity(), "utf-8");
            return AutoTools.unicodeDecode(result);
        } catch (Exception e) {
            AutoTools.log.error("post请求失败了,请查看请求报文日志", e.fillInStackTrace());
            return e.fillInStackTrace().toString();
        }
    }

    /**
     * 通过urlencoded格式完成请求
     *
     * @param url
     * @param param
     * @return
     */
    public String doPostUrl(String url, String param) {
        return doPost(url, param, "url");
    }

    public String doPostJson(String url, String param) {
        return doPost(url, param, "json");
    }

    public String doPostFile(String url, String param) {
        return doPost(url, param, "file");
    }

    public String doPutUrl(String url, String param) {
        try {
            createClient();
            HttpPut put = new HttpPut(url);
            StringEntity userAndNick = new StringEntity(param, "utf-8");
            userAndNick.setContentType("application/x-www-form-urlencoded");
            put.setEntity(userAndNick);
            if(isUseheader){
                //遍历添加map中所有头
                for (String headerKey : headerMap.keySet()) {
                    put.setHeader(headerKey,headerMap.get(headerKey));
                }
            }
            String s = EntityUtils.toString(client.execute(put).getEntity(), "utf-8");
            return AutoTools.unicodeDecode(s);
        } catch (Exception e) {
            AutoTools.log.error("put请求失败", e.fillInStackTrace());
            return e.fillInStackTrace().toString();
        }
    }

    public String doPostXml(String url,String param){
        return doPost(url, param, "xml");
    }

    public String doDelete(String url)  {
        try {
            createClient();
            HttpDelete delete = new HttpDelete(url);
            if(isUseheader){
                //遍历添加map中所有头
                for (String headerKey : headerMap.keySet()) {
                    delete.setHeader(headerKey,headerMap.get(headerKey));
                }
            }
            String result = EntityUtils.toString(client.execute(delete).getEntity(), "utf-8");
            return AutoTools.unicodeDecode(result);
        } catch (Exception e) {
            AutoTools.log.error("delete请求" + url + "失败", e.fillInStackTrace());
            return e.fillInStackTrace().toString();
        }
    }

}
